package com.jeek.jdbc.myCode.preparestatement;

import com.jeek.jdbc.myCode.entity.Girl;
import com.jeek.jdbc.myCode.utils.JDBCUtils;

import java.sql.*;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * @Desc TODO
 * @Author chenmin
 * @Date 2025/11/17
 *
 * PreparedStatement 语句对象
 *
 * 面试题 - 基于PreparedStatement的原生JDBC操作步骤
 * 1.获得连接对象
 * 2.预编译SQL语句，获取语句对象
 * 3.给?占位符传值  从1开始
 * 4.执行查询操作，获取结果集
 * 5.处理结果集
 * 6.关闭资源
 *
 * PreparedStatement的优势
 * 1.通过?占位符传值，查询数据时候避免SQL注入的发生
 * 2.预编译SQL，编译次数比Statement要少，效率高
 *
 * PreparedStatement的劣势
 * 1.输入参数传递，需要给?占位符传值           --->  setXxx(?的位置 , 值)  硬编码  --->  输入参数映射
 * 2.输出参数处理，需要一一获取字段值进行设置    --->  getXxx(字段名)       硬编码  --->  输出参数映射
 * 解决方案：MyBatis 、 MyBatisPlus 、 JPA等等 ORM关系映射框架，完成输入参数映射、输出参数映射
 */
public class GirlDao {

    //需求1：通过姓名模糊查询女生列表
    public List<Girl> selectOneByLikeName(String query){
        List<Girl> list = new ArrayList<>();
        //1.获得连接对象
        Connection conn = JDBCUtils.getConn();
        PreparedStatement ppst = null;
        ResultSet rs = null;
        try {
            //2.预编译SQL语句，获取语句对象
            String sql = "select * from girl where name like concat('%',?,'%')";
            ppst = conn.prepareStatement(sql);
            //3.给?占位符传值
            ppst.setString(1 , query);
            //4.执行查询操作，获取结果集
            rs = ppst.executeQuery();
            //5.处理结果集
            while (rs.next()){
                Girl girl = new Girl();
                girl.setId(rs.getInt("id"));
                girl.setName(rs.getString("name"));
                girl.setSex(rs.getString("sex"));
                String borndateStr = rs.getString("borndate");
                LocalDate borndate = LocalDate.parse(borndateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                girl.setBorndate(borndate);
                girl.setPhone(rs.getString("phone"));
                girl.setBoyfriendId(rs.getInt("boyfriend_id"));
                list.add(girl);
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            //6.关闭资源
            JDBCUtils.close(ppst , conn , rs);
        }
        return list;
    }


    //需求2：插入女生信息（+ 获取主键自增的值）
    public int insert(Girl girl){
        //1.获取连接对象
        Connection conn = JDBCUtils.getConn();
        PreparedStatement ppst = null;
        //2.预编译SQL，获取语句对象
        try {
            String sql = "insert into girl values(NULL,?,DEFAULT,now(),?,NULL,?)";
            //TODO 第一个参数：SQL语句  第二个参数：获取的自增主键
            ppst = conn.prepareStatement(sql , PreparedStatement.RETURN_GENERATED_KEYS);
            //3.给?占位符传值
            ppst.setString(1 , girl.getName());
            ppst.setString(2 , girl.getPhone());
            ppst.setInt(3 , girl.getBoyfriendId());
            //4.执行 增、删、改 操作
            int i = ppst.executeUpdate();
            //TODO 获取自增ID的值
            ResultSet rs = ppst.getGeneratedKeys();
            while (rs.next()){
                int id = rs.getInt(1);
                System.out.println("获取自增ID的值 = "+id);
            }
            return i;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtils.close(ppst , conn , null);
        }
    }

    //需求3：根据手机号更新女生信息
    public int updateGirlByPhone(String phone, String newName, String newSex, Date newBorndate, Integer newBoyfriendId) {
        Connection conn = JDBCUtils.getConn();
        PreparedStatement ppst = null;
        try {
            // 1. 获取数据库连接
            conn = JDBCUtils.getConn();
            // 2. 编写SQL语句（使用?作为参数占位符）
            String sql = "UPDATE girl " +
                    "SET name = ?, sex = ?, borndate = ?,boyfriend_id = ? " +
                    "WHERE phone = ?";
            // 3. 创建PreparedStatement
            ppst = conn.prepareStatement(sql);
            // 4. 给占位符赋值（注意参数顺序与SQL中?的顺序一致）
            ppst.setString(1, newName);
            ppst.setString(2, newSex);
            ppst.setDate(3, newBorndate);
            ppst.setInt(4, newBoyfriendId);
            ppst.setString(5, phone);
            // 5. 执行更新操作，返回受影响的行数
            int i = ppst.executeUpdate();
            return i;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 6. 关闭资源
            JDBCUtils.close(ppst , conn , null);
        }
        return 0;
    }

    //需求4：根据ID删除女生信息
    public int deleteGirlById(Integer id) {
        Connection conn = JDBCUtils.getConn();
        PreparedStatement ppst = null;
        try {
            // 1. 获取数据库连接
            conn = JDBCUtils.getConn();
            // 2. 创建SQL语句
            String sql = "DELETE FROM girl WHERE id = ?";
            // 3. 创建PreparedStatement
            ppst = conn.prepareStatement(sql);
            // 4. 给占位符赋值
            ppst.setInt(1, id);
            // 5. 执行删除操作，返回受影响的行数
            int i = ppst.executeUpdate();
            return i;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(ppst , conn , null);
        }
        return 0;
    }

}
